home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / GIFLIB12.ARJ / GIFFLIP.C < prev    next >
C/C++ Source or Header  |  1991-05-12  |  12KB  |  342 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to rotate image 90 degrees to the right/left or flip the image     *
  7. * horizintally/vertically (mirror).                         *
  8. * Options:                                     *
  9. * -q : quite printing mode.                             *
  10. * -r : rotate 90 degrees to the right (default).                 *
  11. * -l : rotate 90 degrees to the left.                         *
  12. * -x : Mirror the image horizontally (first line switch places with last).   *
  13. * -y : Mirror the image vertically (first column switch places with last).   *
  14. * -h : on line help                                 *
  15. ******************************************************************************
  16. * History:                                     *
  17. * 10 Jul 89 - Version 1.0 by Gershon Elber.                     *
  18. *****************************************************************************/
  19.  
  20. #ifdef __MSDOS__
  21. #include <stdlib.h>
  22. #include <alloc.h>
  23. #endif /* __MSDOS__ */
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28. #include "gif_lib.h"
  29. #include "getarg.h"
  30.  
  31. #define PROGRAM_NAME    "GifFlip"
  32.  
  33. #define FLIP_NONE    0
  34. #define FLIP_RIGHT    1
  35. #define FLIP_LEFT    2
  36. #define FLIP_HORIZ    3
  37. #define FLIP_VERT    4
  38.  
  39. #ifdef __MSDOS__
  40. extern unsigned int
  41.     _stklen = 16384;                 /* Increase default stack size. */
  42. #endif /* __MSDOS__ */
  43.  
  44. #ifdef SYSV
  45. static char *VersionStr =
  46.         "Gif library module,\t\tGershon Elber\n\
  47.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  48. static char
  49.     *CtrlStr = "GifFlip q%- r%- l%- x%- y%- h%- GifFile!*s";
  50. #else
  51. static char
  52.     *VersionStr =
  53.     PROGRAM_NAME
  54.     GIF_LIB_VERSION
  55.     "    Gershon Elber,    "
  56.     __DATE__ ",   " __TIME__ "\n"
  57.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  58. static char
  59.     *CtrlStr =
  60.     PROGRAM_NAME
  61.     " q%- r%- l%- x%- y%- h%- GifFile!*s";
  62. #endif /* SYSV */
  63.  
  64. /* Make some variables global, so we could access them faster: */
  65. static int
  66.     ImageNum = 0;
  67.  
  68. static int LoadImage(GifFileType *GifFile, GifRowType **ImageBuffer);
  69. static int DumpImage(GifFileType *GifFile, GifRowType *ImageBuffer,
  70.                 int Width, int Height, int FlipDirection);
  71. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  72.  
  73. /******************************************************************************
  74. * Interpret the command line and scan the given GIF file.              *
  75. ******************************************************************************/
  76. void main(int argc, char **argv)
  77. {
  78.     int    i, Error, NumFiles, ExtCode, FlipDirection = FLIP_RIGHT,
  79.     RightFlag = FALSE, LeftFlag = FALSE,
  80.     HorizFlag = FALSE, VertFlag = FALSE, HelpFlag = FALSE;
  81.     GifRecordType RecordType;
  82.     GifByteType *Extension;
  83.     char **FileName = NULL;
  84.     GifRowType *ImageBuffer;
  85.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  86.  
  87.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint,
  88.         &RightFlag, &LeftFlag, &HorizFlag, &VertFlag, &HelpFlag,
  89.         &NumFiles, &FileName)) != FALSE ||
  90.         (NumFiles > 1 && !HelpFlag)) {
  91.     if (Error)
  92.         GAPrintErrMsg(Error);
  93.     else if (NumFiles > 1)
  94.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  95.     GAPrintHowTo(CtrlStr);
  96.     exit(1);
  97.     }
  98.  
  99.     if (HelpFlag) {
  100.     fprintf(stderr, VersionStr);
  101.     GAPrintHowTo(CtrlStr);
  102.     exit(0);
  103.     }
  104.  
  105.     if ((i = (RightFlag != 0) + (LeftFlag != 0) +
  106.          (HorizFlag != 0) + (VertFlag != 0)) > 1)
  107.     GIF_EXIT("Only one of -r, -l, -x, -y please.");
  108.     if (i == 0)
  109.     FlipDirection = FLIP_RIGHT;             /* Make it the default. */
  110.     else {
  111.     if (RightFlag) FlipDirection = FLIP_RIGHT;
  112.     if (LeftFlag) FlipDirection = FLIP_LEFT;
  113.     if (HorizFlag) FlipDirection = FLIP_HORIZ;
  114.     if (VertFlag) FlipDirection = FLIP_VERT;
  115.     }
  116.  
  117.     if (NumFiles == 1) {
  118.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  119.         QuitGifError(GifFileIn, GifFileOut);
  120.     }
  121.     else {
  122.     /* Use the stdin instead: */
  123.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  124.         QuitGifError(GifFileIn, GifFileOut);
  125.     }
  126.  
  127.     /* Open stdout for the output file: */
  128.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  129.     QuitGifError(GifFileIn, GifFileOut);
  130.  
  131.     if (RightFlag || LeftFlag) {
  132.     /* Dump out same screen information, but flip Screen Width/Height: */
  133.     if (EGifPutScreenDesc(GifFileOut,
  134.         GifFileIn -> SHeight, GifFileIn -> SWidth,
  135.         GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  136.         GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR)
  137.         QuitGifError(GifFileIn, GifFileOut);
  138.     }
  139.     else {
  140.     /* Dump out exactly same screen information: */
  141.     if (EGifPutScreenDesc(GifFileOut,
  142.         GifFileIn -> SWidth, GifFileIn -> SHeight,
  143.         GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  144.         GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR)
  145.         QuitGifError(GifFileIn, GifFileOut);
  146.     }
  147.  
  148.     /* Scan the content of the GIF file and load the image(s) in: */
  149.     do {
  150.     if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
  151.         QuitGifError(GifFileIn, GifFileOut);
  152.  
  153.     switch (RecordType) {
  154.         case IMAGE_DESC_RECORD_TYPE:
  155.         if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
  156.             QuitGifError(GifFileIn, GifFileOut);
  157.         if (GifFileIn -> IInterlace)
  158.             GIF_EXIT("Cannt flip interlaced images - use GifInter first.");
  159.  
  160.         /* Put the image descriptor to out file: */
  161.         if (RightFlag) {
  162.             /* Rotate to the right: */
  163.             if (EGifPutImageDesc(GifFileOut,
  164.             GifFileIn -> SHeight - GifFileIn -> IHeight -
  165.                         GifFileIn -> ITop,
  166.             GifFileIn -> ILeft,
  167.             GifFileIn -> IHeight, GifFileIn -> IWidth,
  168.             FALSE, GifFileIn -> IBitsPerPixel,
  169.             GifFileIn -> IColorMap) == GIF_ERROR)
  170.                 QuitGifError(GifFileIn, GifFileOut);
  171.         }
  172.         else if (LeftFlag) {
  173.             /* Rotate to the left: */
  174.             if (EGifPutImageDesc(GifFileOut,
  175.             GifFileIn -> ITop,
  176.             GifFileIn -> SWidth - GifFileIn -> IWidth -
  177.                         GifFileIn -> ILeft,
  178.             GifFileIn -> IHeight, GifFileIn -> IWidth,
  179.             FALSE, GifFileIn -> IBitsPerPixel,
  180.             GifFileIn -> IColorMap) == GIF_ERROR)
  181.                 QuitGifError(GifFileIn, GifFileOut);
  182.         }
  183.         else {
  184.             /* No rotation - only flipping vert. or horiz.: */
  185.             if (EGifPutImageDesc(GifFileOut,
  186.             GifFileIn -> ILeft, GifFileIn -> ITop,
  187.             GifFileIn -> IWidth, GifFileIn -> IHeight,
  188.             FALSE, GifFileIn -> IBitsPerPixel,
  189.             GifFileIn -> IColorMap) == GIF_ERROR)
  190.                 QuitGifError(GifFileIn, GifFileOut);
  191.         }
  192.  
  193.         /* Load the image (either Interlaced or not), and dump it    */
  194.         /* fliped as requrested by Flags:                 */
  195.         if (LoadImage(GifFileIn, &ImageBuffer) == GIF_ERROR)
  196.             QuitGifError(GifFileIn, GifFileOut);
  197.         if (DumpImage(GifFileOut, ImageBuffer, GifFileIn -> IWidth,
  198.                 GifFileIn -> IHeight, FlipDirection) == GIF_ERROR)
  199.             QuitGifError(GifFileIn, GifFileOut);
  200.         break;
  201.         case EXTENSION_RECORD_TYPE:
  202.         /* Skip any extension blocks in file: */
  203.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
  204.             QuitGifError(GifFileIn, GifFileOut);
  205.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  206.                             Extension) == GIF_ERROR)
  207.             QuitGifError(GifFileIn, GifFileOut);
  208.  
  209.         /* No support to more than one extension blocks, so discard: */
  210.         while (Extension != NULL) {
  211.             if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR)
  212.             QuitGifError(GifFileIn, GifFileOut);
  213.         }
  214.         break;
  215.         case TERMINATE_RECORD_TYPE:
  216.         break;
  217.         default:            /* Should be traps by DGifGetRecordType. */
  218.         break;
  219.     }
  220.     }
  221.     while (RecordType != TERMINATE_RECORD_TYPE);
  222.  
  223.     if (DGifCloseFile(GifFileIn) == GIF_ERROR)
  224.     QuitGifError(GifFileIn, GifFileOut);
  225.     if (EGifCloseFile(GifFileOut) == GIF_ERROR)
  226.     QuitGifError(GifFileIn, GifFileOut);
  227. }
  228.  
  229. /******************************************************************************
  230. * Routine to read Image out. The image can be Non interlaced only.          *
  231. * The memory required to hold the image is allocate by the routine itself.    *
  232. * Return GIF_OK if succesful, GIF_ERROR otherwise.                  *
  233. ******************************************************************************/
  234. static int LoadImage(GifFileType *GifFile, GifRowType **ImageBufferPtr)
  235. {
  236.     int Size, i;
  237.     GifRowType *ImageBuffer;
  238.  
  239.     /* Allocate the image as vector of column of rows. We cannt allocate     */
  240.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  241.     /* 64k at a time and our image can be bigger than that:             */
  242.     if ((ImageBuffer = (GifRowType *)
  243.     malloc(GifFile -> IHeight * sizeof(GifRowType *))) == NULL)
  244.         GIF_EXIT("Failed to allocate memory required, aborted.");
  245.  
  246.     Size = GifFile -> IWidth * sizeof(GifPixelType);/* One row size in bytes.*/
  247.     for (i = 0; i < GifFile -> IHeight; i++) {
  248.     /* Allocate the rows: */
  249.     if ((ImageBuffer[i] = (GifRowType) malloc(Size)) == NULL)
  250.         GIF_EXIT("Failed to allocate memory required, aborted.");
  251.     }
  252.  
  253.     *ImageBufferPtr = ImageBuffer;
  254.  
  255.     GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  256.     PROGRAM_NAME, ++ImageNum, GifFile -> ILeft, GifFile -> ITop,
  257.                  GifFile -> IWidth, GifFile -> IHeight);
  258.  
  259.     for (i = 0; i < GifFile -> IHeight; i++) {
  260.     GifQprintf("\b\b\b\b%-4d", i);
  261.     if (DGifGetLine(GifFile, ImageBuffer[i], GifFile -> IWidth)
  262.         == GIF_ERROR) return GIF_ERROR;
  263.     }
  264.  
  265.     return GIF_OK;
  266. }
  267.  
  268. /******************************************************************************
  269. * Routine to dump image out. The given Image buffer should always hold the    *
  270. * image sequencially, and Width & Height hold image dimensions BEFORE flip.   *
  271. * Image will be dumped according to FlipDirection.                  *
  272. * Once dumped, the memory holding the image is freed.                  *
  273. * Return GIF_OK if succesful, GIF_ERROR otherwise.                  *
  274. ******************************************************************************/
  275. static int DumpImage(GifFileType *GifFile, GifRowType *ImageBuffer,
  276.                 int Width, int Height, int FlipDirection)
  277. {
  278.     int i, j, Count;
  279.     GifRowType Line;               /* New scan line is copied to it. */
  280.  
  281.     /* Allocate scan line that will fit both image width and height: */
  282.     if ((Line = (GifRowType) malloc((Width > Height ? Width : Height)
  283.                         * sizeof(GifPixelType))) == NULL)
  284.     GIF_EXIT("Failed to allocate memory required, aborted.");
  285.  
  286.     switch (FlipDirection) {
  287.     case FLIP_RIGHT:
  288.         for (Count = Width, i = 0; i < Width; i++) {
  289.         GifQprintf("\b\b\b\b%-4d", Count--);
  290.         for (j = 0; j < Height; j++)
  291.             Line[j] = ImageBuffer[Height - j - 1][i];
  292.         if (EGifPutLine(GifFile, Line, Height) == GIF_ERROR)
  293.                 return GIF_ERROR;
  294.         }
  295.         break;
  296.     case FLIP_LEFT:
  297.         for (i = Width - 1; i >= 0; i--) {
  298.         GifQprintf("\b\b\b\b%-4d", i + 1);
  299.         for (j = 0; j < Height; j++)
  300.             Line[j] = ImageBuffer[j][i];
  301.         if (EGifPutLine(GifFile, Line, Height) == GIF_ERROR)
  302.                 return GIF_ERROR;
  303.         }
  304.         break;
  305.     case FLIP_HORIZ:
  306.         for (i = Height - 1; i >= 0; i--) {
  307.         GifQprintf("\b\b\b\b%-4d", i);
  308.         if (EGifPutLine(GifFile, ImageBuffer[i], Width) == GIF_ERROR)
  309.             return GIF_ERROR;
  310.         }
  311.         break;
  312.     case FLIP_VERT:
  313.         for (Count = Height, i = 0; i < Height; i++) {
  314.         GifQprintf("\b\b\b\b%-4d", Count--);
  315.         for (j = 0; j < Width; j++)
  316.             Line[j] = ImageBuffer[i][Width - j - 1];
  317.         if (EGifPutLine(GifFile, Line, Width) == GIF_ERROR)
  318.                 return GIF_ERROR;
  319.         }
  320.         break;
  321.     }
  322.  
  323.     /* Free the memory used for this image, and the temporary scan line: */
  324.     for (i = 0; i < Height; i++) free((char *) ImageBuffer[i]);
  325.     free((char *) ImageBuffer);
  326.  
  327.     free((char *) Line);
  328.  
  329.     return GIF_OK;
  330. }
  331.  
  332. /******************************************************************************
  333. * Close both input and output file (if open), and exit.                  *
  334. ******************************************************************************/
  335. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  336. {
  337.     PrintGifError();
  338.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  339.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  340.     exit(1);
  341. }
  342.